package com.detrum.detrumdata.newd;


import com.detrum.base.BaseStatic;

public class DFrame {
    private final static int HeaderLen = 8;

    private int src = 0;
    private int dest = 0;
    private int type = 0;
    private int pkg_len = 0;
    private long checksum = 0;

    static long calculateChecksum(byte[] buf, int len) {
        int length = len;
        int i = 0;

        long sum = 0;
        long data ;

        // Handle all pairs
        while (length > 1) {
            // Corrected to include @Andy's edits and various comments on Stack Overflow
		    data = (((buf[i] << 8) & 0xFF00) | ((buf[i + 1]) & 0xFF));
            sum += data;
            // 1's complement carry bit correction in 16-bits (detecting sign extension)
            if ((sum & 0xFFFF0000) > 0) {
                sum = sum & 0xFFFF;
                sum += 1;
            }

            i += 2;
            length -= 2;
       }

       // Handle remaining byte in odd length buffers
       if (length > 0) {
           // Corrected to include @Andy's edits and various comments on Stack Overflow
           sum += (buf[i] << 8 & 0xFF00);
           // 1's complement carry bit correction in 16-bits (detecting sign extension)
           if ((sum & 0xFFFF0000) > 0) {
               sum = sum & 0xFFFF;
               sum += 1;
           }
       }

       // Final 1's complement value correction to 16-bits
       sum = ~sum;
       sum = sum & 0xFFFF;
       return sum;
    }

    public DFrame(byte[] aRawPkt, int packetSize){
        int remOct = packetSize - HeaderLen;
        int b0,b1;

        type = DFrameType.DFRAME_TYPE_NONE;

        if(remOct > 0)
        {
            b0 = aRawPkt[4] & 0xFF;
            b1 = aRawPkt[5] & 0xFF;
            pkg_len =  ((b0 << 8) & 0xFF00) | (b1 & 0xFF) ;
            if( pkg_len != remOct )
            {
                BaseStatic.savaInfoToSD("Packet Len is wrong " + pkg_len + " in packet size " + packetSize);
                return ;
            }

            checksum = calculateChecksum(aRawPkt,packetSize);
            if(checksum !=0 )
            {
                BaseStatic.savaInfoToSD("Packet CheckSum is error! ");
                return ;
            }

            dest = aRawPkt[1];
            src = aRawPkt[2];
            type = aRawPkt[3];

        }
    }

    public DFrame(byte[] aRawPkt, int packetSize,int key){
        int remOct = packetSize - HeaderLen;
        int b0,b1;

        int type = 0;

        if(remOct > 0)
        {
            b0 = aRawPkt[4] & 0xFF;
            b1 = aRawPkt[5] & 0xFF;
            int pkg_len =  ((b0 << 8) & 0xFF00) | (b1 & 0xFF) ;
            if( pkg_len != remOct )
            {
                BaseStatic.savaInfoToSD("Packet Len is wrong !!!!!!!!!!!" + pkg_len + " in packet size " + packetSize);
                return ;
            }

            long checksum = calculateChecksum(aRawPkt,packetSize);
            if(checksum !=0 )
            {
                BaseStatic.savaInfoToSD("Packet CheckSum is error! !!!!!!!!!!");
                return ;
            }

            int dest = aRawPkt[1];
            int src = aRawPkt[2];
            type = aRawPkt[3];
        }
    }

	public static int genDFrame(byte[] buf, int buf_len, int src, int dest, int type,
		byte[] payload, int payload_len){
		int len = 0;
		long check_sum = 0;

		if(buf_len < payload_len + HeaderLen){
			return 0;
		}

		buf[0] = 0x41;
		buf[1] = (byte)dest;
		buf[2] = (byte)src;
		buf[3] = (byte)type;
		//buf[4] = (byte)(( payload_len >> 24 ) & 0xFF);
		//buf[5] = (byte)(( payload_len >> 16 ) & 0xFF);
		buf[4] = (byte)(( payload_len >> 8 ) & 0xFF);
		buf[5] = (byte)(payload_len  & 0xFF);
		buf[HeaderLen-2] = 0;
		buf[HeaderLen-1] = 0;
		System.arraycopy(payload,0,buf,HeaderLen,payload_len);

		len = payload_len + HeaderLen;

        check_sum = calculateChecksum(buf,len);
        buf[HeaderLen-2] = (byte)(( check_sum >> 8 ) & 0xFF);
        buf[HeaderLen-1] = (byte)(check_sum  & 0xFF);
		
		return len;
	}


	public static int genDFrameHeader(byte[] buf, int buf_len, int src, int dest, int type, int payload_len){
		int len = 0;
		long check_sum = 0;

		if(buf_len < payload_len + HeaderLen){
			return 0;
		}

		buf[0] = 0x41;
		buf[1] = (byte)dest;
		buf[2] = (byte)src;
		buf[3] = (byte)type;
		//buf[4] = (byte)(( payload_len >> 24 ) & 0xFF);
		//buf[5] = (byte)(( payload_len >> 16 ) & 0xFF);
		buf[4] = (byte)(( payload_len >> 8 ) & 0xFF);
		buf[5] = (byte)(payload_len  & 0xFF);
		buf[HeaderLen-2] = 0;
		buf[HeaderLen-1] = 0;

		len = payload_len + HeaderLen;

        check_sum = calculateChecksum(buf,len);
        buf[HeaderLen-2] = (byte)(( check_sum >> 8 ) & 0xFF);
        buf[HeaderLen-1] = (byte)(check_sum  & 0xFF);
		
		return len;
	}

	public static int genDFrameAccessoryAttached(byte[] buf, int buf_len){

        byte[] payload = {0x0,(byte)DProtocolType.D_FRAME_ANDROID_ACCESSORY_ATTACHED};

		return genDFrame(buf,buf_len,
                DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,DFrameEntity.DFRAME_ENTITY_IWT_GS,
                DFrameType.DFRAME_TYPE_DPROTOCOL,payload,payload.length);
	}
	
	public static int genDFrameStartVideoTrans(byte[] buf, int buf_len){

        byte[] payload = {0x0,(byte)DProtocolType.D_FRAME_ANDROID_START_VIDEO_TRANS};

		return genDFrame(buf,buf_len,
                DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,DFrameEntity.DFRAME_ENTITY_IWT_GS,
                DFrameType.DFRAME_TYPE_DPROTOCOL,payload,payload.length);
	}

    public static int genDFrameStopVideoTrans(byte[] buf, int buf_len){

        byte[] payload = {0x0,(byte)DProtocolType.D_FRAME_ANDROID_STOP_VIDEO_TRANS};

        return genDFrame(buf,buf_len,
                DFrameEntity.DFRAME_ENTITY_MOBILE_DEVICE,DFrameEntity.DFRAME_ENTITY_IWT_GS,
                DFrameType.DFRAME_TYPE_DPROTOCOL,payload,payload.length);
    }

    public static int getDFrameLen(byte[] buf, int offset, int buf_len){
        int b0,b1;
        int len;
        if( offset + HeaderLen < buf_len) {
            return 0;
        }

        b0 = buf[offset + 4] & 0xFF;
        b1 = buf[offset + 5] & 0xFF;
        len =  ((b0 << 8) & 0xFF00) | (b1 & 0xFF) ;
        return len;
    }

    public int getType(){
        return type;
    }

    public int getLen(){   return pkg_len ;  }

    public long getCheckSum(){   return checksum ;  }
}
